#include <Qt>
#include <QtGui>
#include <QtOpenGL>
#include <QGLWidget>
#include <math.h>
#include <stdlib.h>
#include "agente.h"
#include "obstaculo.h"
#include "nonplayablecharacter.h"
#include "waypoint.h"
#include "cenario.h"
#include "glwidget.h"

FILE *fp;
GLfloat angleY = 0; //the rotation value
GLfloat angleX = 0; //the rotation value
GLfloat passoX = 0;
GLfloat passoZ = 0;
float raio = (float)TAMANHO_OBSTACULO/(float)100;
Cenario *cenario;
int valorTerreno;
bool INSERE_NPC;
bool INSERE_OBSTACULO;
bool INSERE_AGENTE;
bool INSERE_OBJETIVO;
bool INSERE_WAYPOINT;
bool INSERE_TERRENO;
int timerID;
bool played;
bool mostraGrid;
vector<Nodo> nodos;
int indice;
bool terminoAestrela;


    GLWidget::GLWidget(QWidget *parent)
        : QGLWidget(parent)
    {
        cenario = new Cenario();
        INSERE_NPC = false;
        INSERE_OBSTACULO = false;
        INSERE_AGENTE = false;
        INSERE_OBJETIVO = false;
        INSERE_WAYPOINT = false;
        ALGORITMO_NPC = 0;
        played = false;
        mostraGrid = false;
        terminoAestrela = false;
        fp = fopen("nosvisitados.txt","w");
    }

    GLWidget::~GLWidget()
    {        
    }
    void GLWidget::setAlgoritmo(int Algoritmo){
        ALGORITMO_NPC = Algoritmo;
    }
    void GLWidget::setValorTerreno(int ValorTerreno){
        valorTerreno = ValorTerreno;
    }
    void GLWidget::cliqueBotaoAgente(){
        INSERE_NPC = false;
        INSERE_OBSTACULO = false;
        INSERE_AGENTE = true;
        INSERE_OBJETIVO = false;
        INSERE_WAYPOINT = false;
        INSERE_TERRENO = false;
    }

    void GLWidget::cliqueBotaoObjetivo(){
        INSERE_NPC = false;
        INSERE_OBSTACULO = false;
        INSERE_AGENTE = false;
        INSERE_OBJETIVO = true;
        INSERE_WAYPOINT = false;
        INSERE_TERRENO = false;
    }

    void GLWidget::cliqueBotaoObstaculo(){
        INSERE_NPC = false;
        INSERE_OBSTACULO = true;
        INSERE_AGENTE = false;
        INSERE_OBJETIVO = false;
        INSERE_WAYPOINT = false;
        INSERE_TERRENO = false;
    }

    void GLWidget::cliqueBotaoNPC(){
        INSERE_NPC = true;
        INSERE_OBSTACULO = false;
        INSERE_AGENTE = false;
        INSERE_OBJETIVO = false;
        INSERE_WAYPOINT = false;
        INSERE_TERRENO = false;
    }

    void GLWidget::cliqueBotaoWaypoint(){
        INSERE_NPC = false;
        INSERE_OBSTACULO = false;
        INSERE_AGENTE = false;
        INSERE_OBJETIVO = false;
        INSERE_WAYPOINT = true;
        INSERE_TERRENO = false;
    }
    void GLWidget::cliqueBotaoTerreno(){
        INSERE_NPC = false;
        INSERE_OBSTACULO = false;
        INSERE_AGENTE = false;
        INSERE_OBJETIVO = false;
        INSERE_WAYPOINT = false;
        INSERE_TERRENO = true;
    }

    void GLWidget::initializeGL()
    {
        glOrtho(-1,1,-1,1,-0.9,1.1);
        glEnable(GL_DEPTH);
        glEnable(GL_DEPTH_TEST);        
    }

    void GLWidget::play(){
        if(played ==false){
            timerID = startTimer(33);
            played =true;
        }
    }

    void GLWidget::pause(){
        if(played == true){
            killTimer(timerID);
            played =false;
        }
    }

    void GLWidget::paintGL()
    {
        glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glPushMatrix();
        glTranslated(0,0,passoZ);
        glRotated(angleY,1,0,0);
        glRotated(angleX,0,1,0);

        glBegin(GL_QUADS);		// Desenha o mundo
        glColor3f(0.1f,0.2f,0.4f);
        glVertex3f( 1.0f, 1.0f,-1.0f);	// acimaDireita (Topo)
        glVertex3f(-1.0f, 1.0f,-1.0f);	// acimaEsquerda (Topo)
        glVertex3f(-1.0f, 1.0f, 1.0f);	// abaixoEsquerda (Topo)
        glVertex3f( 1.0f, 1.0f, 1.0f);	// abaixoDireita (Topo)
        glColor3f(0.1f,0.2f,0.4f);
        glVertex3f( 1.0f,-1.0f, 1.0f);	// acimaDireita (Fundo)
        glVertex3f(-1.0f,-1.0f, 1.0f);	// acimaEsquerda (Fundo)
        glVertex3f(-1.0f,-1.0f,-1.0f);	// abaixoEsquerda (Fundo)
        glVertex3f( 1.0f,-1.0f,-1.0f);	// abaixoDireita (Fundo)
        glColor3f(0.1f,0.2f,0.4f);
        glVertex3f( 1.0f, 1.0f, 1.0f);	// Frente
        glVertex3f(-1.0f, 1.0f, 1.0f);
        glVertex3f(-1.0f,-1.0f, 1.0f);
        glVertex3f( 1.0f,-1.0f, 1.0f);
        glColor3f(0.92f,0.92f,0.92f);
        glVertex3f( 1.0f,-1.0f,-1.0f);	// Costas
        glVertex3f(-1.0f,-1.0f,-1.0f);
        glVertex3f(-1.0f, 1.0f,-1.0f);
        glVertex3f( 1.0f, 1.0f,-1.0f);
        glColor3f(0.1f,0.2f,0.4f);
        glVertex3f(-1.0f, 1.0f, 1.0f);	// Esquerda
        glVertex3f(-1.0f, 1.0f,-1.0f);
        glVertex3f(-1.0f,-1.0f,-1.0f);
        glVertex3f(-1.0f,-1.0f, 1.0f);
        glColor3f(0.1f,0.2f,0.4f);
        glVertex3f( 1.0f, 1.0f,-1.0f);	// Direita
        glVertex3f( 1.0f, 1.0f, 1.0f);
        glVertex3f( 1.0f,-1.0f, 1.0f);
        glVertex3f( 1.0f,-1.0f,-1.0f);
        glEnd();

        //Desenha o grid
        if(mostraGrid){
            glColor3f(0.f,0.f,0.f);
            glBegin(GL_POINTS);
                for(int k=0;k<101;k++){
                    for(int l=0;l<101;l++){
                        glVertex2f( convertGridMundo(k),convertGridMundo(l));
                    }
                }
            glEnd();
        }

        if(terminoAestrela){
            glColor3f(0.f,0.f,0.f);

            glBegin(GL_POINTS);
                for(int k=0;k<nodos.at(indice).rotaX.size();k++){
                   //fprintf(fp,"AAAAAAAAAAA FINAL %d ,%d  %d  %d\n",nodos.at(indice).rotaX.at(k),nodos.at(indice).rotaY.at(k) );
                   glVertex2f( convertGridMundo( nodos.at(indice).rotaX.at(k) ),convertGridMundo(nodos.at(indice).rotaY.at(k)) );
                }
            glEnd();


        }


        //desenha os obstaculos
        
        for(int i = 0; i<cenario->getListadeObstaculosSize();i++){            
            glBegin(GL_QUADS);
            glColor3f(0.2*cenario->getObstaculo(i)->getValor()/50000,0.2*cenario->getObstaculo(i)->getValor()/50000,0.8f*cenario->getObstaculo(i)->getValor()/50000);
            glVertex3f( convertGridMundo(cenario->getObstaculo(i)->getx())-0.04,convertGridMundo(cenario->getObstaculo(i)->gety())-0.04,-0.9999);
            glVertex3f( convertGridMundo(cenario->getObstaculo(i)->getx())+0.04,convertGridMundo(cenario->getObstaculo(i)->gety())-0.04,-0.9999);
            glVertex3f( convertGridMundo(cenario->getObstaculo(i)->getx())+0.04,convertGridMundo(cenario->getObstaculo(i)->gety())+0.04,-0.9999);
            glVertex3f( convertGridMundo(cenario->getObstaculo(i)->getx())-0.04,convertGridMundo(cenario->getObstaculo(i)->gety())+0.04,-0.9999);
            glEnd();
        }


        //desenha os NPCS
        glColor3f(1.f,0.f,0.13f);
        for(int i = 0; i<cenario->getListadeNPCsSize();i++){            
            glBegin(GL_TRIANGLE_FAN);
                for(float phi=0; phi<=360; phi+=1){
                    double posicaoX;
                    double posicaoY;
                    if(cenario->getNPC(i)->getEstado() != 3){
                        if(cenario->getNPC(i)->getEstado() == 0)
                            glColor3f(0.15,0.65,0.15);
                        //verde
                        if(cenario->getNPC(i)->getEstado() == 1)
                            glColor3f(0.55,0.25,0.75);
                        //roxo
                        if(cenario->getNPC(i)->getEstado() == 2)
                            glColor3f(0.65,0.05,0.05);
                        //vermelho
                        posicaoX = convertGridMundo(cenario->getNPC(i)->getx());
                        posicaoY = convertGridMundo(cenario->getNPC(i)->gety());
                    }
                    else{
                            glColor3f(0.2f,0.6f,0.6f);
                        posicaoX = cenario->getNPC(i)->getxCont();
                        posicaoY = cenario->getNPC(i)->getyCont();
                    }
                    glVertex3f((posicaoX + cos(phi)*raio), (posicaoY+sin(phi)*raio), -0.99999);
                }
            glEnd();
        }

        //desenha os Waypoint
        glColor3f(1,0.02,0.02);
        for(int i = 0; i<cenario->getListadeWaypointsSize();i++){
            glBegin(GL_TRIANGLE_FAN);
                for(float phi=0; phi<=360; phi+=1){
                    double posicaoX = convertGridMundo(cenario->getWaypoint(i)->getx());
                    double posicaoY = convertGridMundo(cenario->getWaypoint(i)->gety());
                    glVertex3f((posicaoX + cos(phi)*raio), (posicaoY+sin(phi)*raio), -0.99999);
                }
            glEnd();
        }

        //desenha o agente
        if(cenario->getAgente() !=NULL){
            glColor3f(0.5f,0.5f,0.5f);
            glBegin(GL_TRIANGLE_FAN);            
            for(float phi=0; phi<=360; phi+=1){
                double posicaoX = convertGridMundo(cenario->getAgente()->getx());
                double posicaoY = convertGridMundo(cenario->getAgente()->gety());
                glVertex3f((posicaoX + cos(phi)*raio), (posicaoY+sin(phi)*raio), -0.99999);
            }
            glEnd();
        }

        //desenha o objetivo
        if(cenario->getObjetivo() !=NULL){
            glColor3f(0.0f,0.0,0.0f);
            glBegin(GL_TRIANGLE_FAN);
            for(float phi=0; phi<=360; phi+=1){
                  double posicaoX = convertGridMundo(cenario->getObjetivo()->getx());
                  double posicaoY = convertGridMundo(cenario->getObjetivo()->gety());
                  glVertex3f((posicaoX + cos(phi)*raio), (posicaoY+sin(phi)*raio), -0.99998);
            }
            glEnd();
        }

        glPopMatrix();
        glFlush();
    }

    void GLWidget::timerEvent(QTimerEvent *event){
        //int x,y;

            for(int i= 0 ;i<cenario->getListadeNPCsSize();i++){
                int tempX = cenario->getNPC(i)->getx();
                int tempY = cenario->getNPC(i)->gety();

                //realiza o algoritmo de campos potenciais
                if(cenario->getNPC(i)->getEstado() == 0)cenario->getNPC(i)->campos_potenciais(cenario->getGrid());

                //realiza o waypoint navigarion
                else if(cenario->getNPC(i)->getEstado() == 1){
                    bool encontrouWaypoint = false;
                    for(int j=0; j<cenario->getListadeWaypointsSize(); j++ ){
                        //verifica se o waypoint atual e o destino do npc
                        if(cenario->getNPC(i)->getNextWaypoint() == cenario->getWaypoint(j)->getIdentificador() ){
                            encontrouWaypoint =true;
                            if( j+1 < cenario->getListadeWaypointsSize()){
                                cenario->getNPC(i)->waypoint_nav( cenario->getWaypoint(j)->getx(),  cenario->getWaypoint(j)->gety(),  cenario->getWaypoint(j+1)->getIdentificador());
                            }
                            else{
                                cenario->getNPC(i)->waypoint_nav( cenario->getWaypoint(j)->getx(),  cenario->getWaypoint(j)->gety(),  cenario->getWaypoint(0)->getIdentificador());
                            }
                        }
                        //caso chegue no ultimo elemento e nao tenha encontrado o waypoint de destino seta como destino o primeiro waypoint da lista de waypoints
                        if(encontrouWaypoint == false && j == cenario->getListadeWaypointsSize()-1){
                            //se existe apenas 1 waypoint o proximo waypoint e ele mesmo
                            if(j==0){
                                cenario->getNPC(i)->waypoint_nav( cenario->getWaypoint(0)->getx(),  cenario->getWaypoint(0)->gety(),  cenario->getWaypoint(0)->getIdentificador());
                            }
                            //indica como proximo waypoint o segundo elemento da lista de waypoints
                            else{
                                cenario->getNPC(i)->waypoint_nav( cenario->getWaypoint(0)->getx(),  cenario->getWaypoint(0)->gety(),  cenario->getWaypoint(1)->getIdentificador());
                            }
                        }
                    }

                    if(cenario->detectaColisao( cenario->getNPC(i)->getx(), cenario->getNPC(i)->gety(), TAMANHO_OBSTACULO/2) ){
                        if( !cenario->detectaColisao( cenario->getNPC(i)->getx(), tempY, TAMANHO_OBSTACULO/2 ) ){
                            cenario->getNPC(i)->sety( tempY );
                        }
                        else if( !cenario->detectaColisao( tempX,  cenario->getNPC(i)->gety(), TAMANHO_OBSTACULO/2 ) ){
                            cenario->getNPC(i)->setx( tempX );
                        }
                        else{
                            cenario->getNPC(i)->setx( tempX );
                            cenario->getNPC(i)->sety( tempY );
                        }
                    }

                    if( cenario->getAgente() != NULL ){
                        if( cenario->getNPC(i)->avistou(cenario->getAgente()->getx(), cenario->getAgente()->gety() ) ){
                            cenario->getNPC(i)->setEstado(2);
                        }
                    }
                }
                else if(cenario->getNPC(i)->getEstado() == 2){
                    if(cenario->getAgente() !=NULL){
                        cenario->getNPC(i)->perseguicao(cenario->getAgente()->getx(), cenario->getAgente()->gety() );
                    }
                    if(cenario->detectaColisao( cenario->getNPC(i)->getx(), cenario->getNPC(i)->gety(), TAMANHO_OBSTACULO/2) ){
                        if( !cenario->detectaColisao( cenario->getNPC(i)->getx(), tempY, TAMANHO_OBSTACULO/2 ) ){
                            cenario->getNPC(i)->sety( tempY );
                        }
                        else if( !cenario->detectaColisao( tempX,  cenario->getNPC(i)->gety(), TAMANHO_OBSTACULO/2 ) ){
                            cenario->getNPC(i)->setx( tempX );
                        }
                        else{
                            cenario->getNPC(i)->setx( tempX );
                            cenario->getNPC(i)->sety( tempY );
                        }
                    }
                }
                else if(cenario->getNPC(i)->getEstado() == 3){
                    calcula_forca(i);
                }

            }

        updateGL();
    }


    void GLWidget::aEstrela(){
        terminoAestrela = false;
        Nodo nodo;
        int **grid = cenario->getGrid();
        nodo.x = cenario->getAgente()->getx();
        nodo.y = cenario->getAgente()->gety();
        int xDestino = cenario->getObjetivo()->getx();
        int yDestino = cenario->getObjetivo()->gety();
        bool marcaVisitadas[TAMANHO_GRID][TAMANHO_GRID];

        nodos.erase(nodos.begin(),nodos.end() );


        for(int v=0;v<TAMANHO_GRID;v++){
            for(int b=0;b<TAMANHO_GRID;b++){
                marcaVisitadas[v][b] = false;
            }
        }



        if(nodo.custo<=VAZIO_GRID){
            nodo.custo = heuristica(nodo.x,nodo.y,xDestino,yDestino)+10000;
        }
        else{
            nodo.custo = heuristica(nodo.x,nodo.y,xDestino,yDestino)+10000;
        }

        nodo.rotaX.push_back(nodo.x);
        nodo.rotaY.push_back(nodo.y);

        marcaVisitadas[nodo.x][nodo.x] = true;

        int cont=1;
        while( true ){
            fprintf(fp,"Numero no visitado %d  Coordenada (%d %d)  Destino (%d %d)\n",cont,nodo.x,nodo.y,xDestino,yDestino);
            //Gera os filhos
            for(int i=-1;i<=1;i++){
                for(int j=-1;j<=1;j++){
                    if(i==0 && j==0){
                    }
                    else{
                        Nodo temp;
                        if( (nodo.x+i>=0) && (nodo.y+j>=0) && (nodo.x+i<=TAMANHO_GRID-1) && (nodo.y+j<=TAMANHO_GRID-1) ){
                            if( grid[nodo.x+i][nodo.y+j] < OBSTACULO_GRID  && !(marcaVisitadas[nodo.x+i][nodo.y+j]) ){
  
                                temp.x=nodo.x+i;
                                temp.y=nodo.y+j;
                                if(grid[temp.x][temp.y]<=VAZIO_GRID){
                                    temp.custo=10000+heuristica(temp.x,temp.y,xDestino,yDestino)+nodo.custo;;
                                }
                                else{
                                    temp.custo=grid[nodo.x+i][nodo.y+j]+heuristica(temp.x,temp.y,xDestino,yDestino)+nodo.custo;;
                                }

                                for(unsigned int k=0;k<nodo.rotaX.size();k++){
                                    temp.rotaX.push_back( nodo.rotaX.at(k) );
                                    temp.rotaY.push_back( nodo.rotaY.at(k) );
                                }
                                temp.rotaX.push_back( temp.x);
                                temp.rotaY.push_back( temp.y );

                                nodos.push_back(temp);

                                temp.custo=0;
                                temp.x=0;
                                temp.y=0;
                                temp.rotaX.erase(temp.rotaX.begin(),temp.rotaX.end() );
                                temp.rotaY.erase(temp.rotaY.begin(),temp.rotaY.end() );
                            }
                        }
                    }
                    marcaVisitadas[nodo.x+i][nodo.y+j] = true;
                }
            }


            //pega o nodo de menor valor
            int menorCusto = 99999999;

            for(unsigned int i=0;i<nodos.size();i++){
                if(nodos.at(i).custo<menorCusto){
                    indice = i;
                    menorCusto = nodos.at(i).custo;
                }
            }


            nodo.x = nodos.at(indice).x;
            nodo.y = nodos.at(indice).y;
            nodo.custo = nodos.at(indice).custo;
            nodo.rotaX.erase(nodo.rotaX.begin(),nodo.rotaX.end() );
            nodo.rotaY.erase(nodo.rotaY.begin(),nodo.rotaY.end() );
            for(unsigned int k=0;k<nodos.at(indice).rotaX.size();k++){
                   nodo.rotaX.push_back( nodos.at(indice).rotaX.at(k) );
                   nodo.rotaY.push_back( nodos.at(indice).rotaY.at(k) );
            }

            //fprintf(fp,"%d ,%d  -  %d, %d  -  %d  %d\n",nodos.at(indice).x,nodos.at(indice).y,nodo.x,nodo.y,xDestino,yDestino);
            if( (xDestino-nodo.x)==0  ){
                if( (yDestino-nodo.y)==0  ){
                    terminoAestrela = true;
                    fprintf(fp,"Numero no visitado %d  Coordenada (%d %d)  Destino (%d %d)\n",cont,nodo.x,nodo.y,xDestino,yDestino);
                    return;
                }
            }
            cont++;
            nodos.erase(nodos.begin() + indice);            
        }
        terminoAestrela = true;
        //fprintf(fp,"FINAL %d ,%d  -  %d, %d  -  %d  %d\n",nodos.at(indice).x,nodos.at(indice).y,nodo.x,nodo.y,xDestino,yDestino);
    }

    int GLWidget::heuristica(int x,int y,int xDestino,int yDestino){


        int passosDiagonal=0;
        int passosRetos=0;
        if( abs(xDestino-x) <= abs(yDestino-y) ){
            passosDiagonal = abs(xDestino-x);
            passosRetos = abs ( abs(yDestino-y) - abs(xDestino-x) );
        }

        if( ((passosDiagonal + passosRetos)*10000 )!=0)return (passosDiagonal + passosRetos)*10000;
        else return -1;
    }

    double GLWidget::convertGridMundo(int x){
        double coord = (double)((x-(TAMANHO_GRID-1)/2 )*2)/(double)(TAMANHO_GRID-1);
        return coord;
    }
    int GLWidget::convertMundoGrid(double x){
        int coord = (int)round( (x * (TAMANHO_GRID-1))/ 2 + (TAMANHO_GRID-1)/2 );
        return coord;
    }

    void GLWidget::keyPressEvent(QKeyEvent * event){

        if(event->key() == 'G'){
                mostraGrid = !mostraGrid;
        }

        /*if(event->key() == 'W')
                passoZ += 0.1;
        if(event->key() == 'S')
                passoZ -= 0.1;
        if(event->key() == 'A')
                angleX -= 5;
        if(event->key() == 'D')
                angleX += 5;
        if(event->key() == 'Q')
                angleY += 5;
        if(event->key() == 'E')
                angleY -= 5;*/
        if(cenario->getAgente() != NULL){
            int x = cenario->getAgente()->getx();
            int y = cenario->getAgente()->gety();
            if(event->key() == 'W' && (!cenario->detectaColisao(cenario->getAgente()->getx(),cenario->getAgente()->gety()+1, TAMANHO_OBSTACULO/2 )) ){
                if(cenario->getAgente()->gety() + 1 < TAMANHO_GRID-1)y = cenario->getAgente()->gety() + 1;
                cenario->getAgente()->sety(y);
            }
            if(event->key() == 'S' && (!cenario->detectaColisao(cenario->getAgente()->getx(),cenario->getAgente()->gety()-1, TAMANHO_OBSTACULO/2 ) ) ){
                if(cenario->getAgente()->gety() - 1 > 0)y = cenario->getAgente()->gety() - 1;
                cenario->getAgente()->sety(y);
            }
            if(event->key() == 'A' && (!cenario->detectaColisao(cenario->getAgente()->getx()-1,cenario->getAgente()->gety(), TAMANHO_OBSTACULO/2 ) ) ){
                if(cenario->getAgente()->getx() - 1 > 0)x = cenario->getAgente()->getx() - 1;
                cenario->getAgente()->setx(x);
            }
            if(event->key() == 'D' && (!cenario->detectaColisao(cenario->getAgente()->getx()+1,cenario->getAgente()->gety(), TAMANHO_OBSTACULO/2 ) ) ){
                if(cenario->getAgente()->getx() + 1 < TAMANHO_GRID-1)x = cenario->getAgente()->getx() + 1;
                cenario->getAgente()->setx(x);
            }
            if(event->key() == 'Q' && (!cenario->detectaColisao(cenario->getAgente()->getx()-1,cenario->getAgente()->gety()+1, TAMANHO_OBSTACULO/2 )) ){
                if(cenario->getAgente()->getx() - 1 > 0)x = cenario->getAgente()->getx() - 1;
                if(cenario->getAgente()->gety() + 1 < TAMANHO_GRID-1)y = cenario->getAgente()->gety() + 1;
                cenario->getAgente()->sety(y);
                cenario->getAgente()->setx(x);
            }
            if(event->key() == 'E' && (!cenario->detectaColisao(cenario->getAgente()->getx()+1,cenario->getAgente()->gety()+1, TAMANHO_OBSTACULO/2 ) ) ){
                if(cenario->getAgente()->getx() + 1 < TAMANHO_GRID-1)x = cenario->getAgente()->getx() + 1;
                if(cenario->getAgente()->gety() + 1 < TAMANHO_GRID-1)y = cenario->getAgente()->gety() + 1;
                cenario->getAgente()->sety(y);
                cenario->getAgente()->setx(x);
            }
            if(event->key() == 'Z' && (!cenario->detectaColisao(cenario->getAgente()->getx()-1,cenario->getAgente()->gety()-1, TAMANHO_OBSTACULO/2 ) ) ){
                if(cenario->getAgente()->getx() - 1 > 0)x = cenario->getAgente()->getx() - 1;
                if(cenario->getAgente()->gety() - 1 > 0)y = cenario->getAgente()->gety() - 1;
                cenario->getAgente()->setx(x);
                cenario->getAgente()->sety(y);
            }
            if(event->key() == 'C' && (!cenario->detectaColisao(cenario->getAgente()->getx()+1,cenario->getAgente()->gety()-1, TAMANHO_OBSTACULO/2 ) ) ){
                if(cenario->getAgente()->getx() + 1 < TAMANHO_GRID-1)x = cenario->getAgente()->getx() + 1;
                if(cenario->getAgente()->gety() - 1 > 0)y = cenario->getAgente()->gety() - 1;
                cenario->getAgente()->setx(x);
                cenario->getAgente()->sety(y);
            }
            if(event->key() == 'O'){

                if(cenario->getAgente()!=NULL && cenario->getObjetivo()!=NULL )aEstrela();
            }
            if(event->key() == '1'){
                ALGORITMO_NPC = 0;
            }
            if(event->key() == '2'){
                ALGORITMO_NPC = 1;
            }
            if(event->key() == '3'){
                ALGORITMO_NPC = 2;
            }
        }
        updateGL();
    }

    void GLWidget::resizeGL(int width, int height)
    {
        //int side = qMin(width, height);
        glViewport(-1, -1, width, height);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
    }

    void GLWidget::mousePressEvent(QMouseEvent *event)
    {         
        //converte as coordenadas recebidas em pixels para a coordenada respectiva no mundo
        double posicaoXa = 2* (double)event->x()/(double)width() -1;
        double posicaoYa = (-1) * (2* (double)event->y()/(double)height() -1 );
        int posicaoX =  convertMundoGrid(posicaoXa);
        int posicaoY =  convertMundoGrid(posicaoYa);

        if(event->button() == Qt::LeftButton){
            if(INSERE_NPC && !cenario->detectaColisao(posicaoX,posicaoY,TAMANHO_OBSTACULO/2)){
                this->setCursor(Qt::WaitCursor);
                NonPlayableCharacter *a;

                if(ALGORITMO_NPC == 1){
                    if(cenario->getListadeWaypointsSize() > 0){
                        a = new NonPlayableCharacter(posicaoX, posicaoY, 1, 1, 10,raio, cenario->getWaypoint(0)->getIdentificador());
                    }
                    else{
                        a = new NonPlayableCharacter(posicaoX, posicaoY, 1, 1, 10,raio, -1);
                    }
                }
                else if(ALGORITMO_NPC == 0){
                    a = new NonPlayableCharacter(posicaoX, posicaoY, 0, 1, 10,raio,0);
                }
                else if(ALGORITMO_NPC == 2){
                    a = new NonPlayableCharacter(posicaoX, posicaoY, 2, 1, 10,raio,0);
                }
                else if(ALGORITMO_NPC == 3){
                    a = new NonPlayableCharacter(posicaoXa, posicaoYa, 3, 1, 10,raio,0);
                }

                cenario->addNPC( a );
                this->unsetCursor();
            }
            if(INSERE_OBSTACULO && !cenario->detectaColisao(posicaoX,posicaoY,TAMANHO_OBSTACULO) ){
                this->setCursor(Qt::WaitCursor);
                Obstaculo *a = new Obstaculo(posicaoX, posicaoY, 0, 1, 2, raio);
                float cor[4] = {0.2f,0.2f,0.8f};
                a->setRGBA(cor);
                cenario->addObstaculo( a );
                this->unsetCursor();
            }
            if(INSERE_TERRENO && !cenario->detectaColisao(posicaoX,posicaoY,TAMANHO_OBSTACULO) ){
                this->setCursor(Qt::WaitCursor);
                Obstaculo *a = new Obstaculo(posicaoX, posicaoY, 0, 1, 2, raio,valorTerreno);
                float cor[4] = {0.2*valorTerreno/50000,0.2*valorTerreno/50000,0.8*valorTerreno/50000,1};
                a->setRGBA(cor);
                cenario->addObstaculo( a );
                this->unsetCursor();

            }
            if(INSERE_AGENTE && cenario->getAgente() == NULL && !cenario->detectaColisao(posicaoX,posicaoY,TAMANHO_OBSTACULO/2)){
                this->setCursor(Qt::WaitCursor);
                Agente *a = new Agente(posicaoX, posicaoY, 0, 1, 100, raio);
                cenario->addAgente( a );
                this->unsetCursor();
            }
            if(INSERE_OBJETIVO && cenario->getObjetivo() == NULL && !cenario->detectaColisao(posicaoX,posicaoY,TAMANHO_OBSTACULO/2)){                
                this->setCursor(Qt::WaitCursor);
                Objetivo *a = new Objetivo(posicaoX, posicaoY, 0, 1, 100, raio);
                cenario->addObjetivo( a );
                this->unsetCursor();
            }
            if(INSERE_WAYPOINT && !cenario->detectaColisao(posicaoX,posicaoY,TAMANHO_OBSTACULO/2)){
                this->setCursor(Qt::WaitCursor);
                Waypoint *a;
                if(cenario->getListadeWaypointsSize() != 0){
                    int ident = cenario->getWaypoint( cenario->getListadeWaypointsSize()-1 )->getIdentificador() + 1;
                    a = new Waypoint(posicaoX, posicaoY, 0, 1, 100, raio, ident);
                }
                else {
                    a = new Waypoint(posicaoX, posicaoY, 0, 1, 100, raio, 0);
                }
                cenario->addWaypoint( a );
                this->unsetCursor();
            }
        }
        if(event->button() == Qt::RightButton){
            this->setCursor(Qt::WaitCursor);
            cenario->removeElemento(posicaoX,posicaoY);
            this->unsetCursor();
        }
        updateGL();
    }

    void GLWidget::limparCenario(){
        cenario->limpaCenario();
        updateGL();
    }

    void GLWidget::calcula_forca( int i){
        double forcaX = 0;
        double forcaY = 0;
        double distancia = 0;
        double angulo = 0;

        if(cenario->getObjetivo() == NULL ) return;

        distancia = sqrt( pow( ( convertGridMundo(cenario->getObjetivo()->getx()) - cenario->getNPC(i)->getxCont() ), 2)+ pow( ( convertGridMundo(cenario->getObjetivo()->gety()) - cenario->getNPC(i)->getyCont() ), 2) ) ;

		//alcancou o objetivo
        if(distancia < 0.02)return;

        //calcula o angulo da forca
		angulo = asin( (double)( convertGridMundo(cenario->getObjetivo()->gety()) - cenario->getNPC(i)->getyCont() )/distancia ) ;
		
		//calcula a componete da forca no eixo X realizada pelo objetivo no NPC
        if( convertGridMundo(cenario->getObjetivo()->getx()) >= cenario->getNPC(i)->getxCont() )forcaX = ( cenario->getObjetivo()->getForca()/pow(distancia,2) )*cos(angulo);
        else forcaX = (-1)*( cenario->getObjetivo()->getForca()/pow(distancia,2) )*cos(angulo);

		//calcula a componete da forno eixo Y realizada pelo objetivo no NPC
        forcaY = ( cenario->getObjetivo()->getForca()/pow(distancia,2) )*sin(angulo);

		//para cada agente do cenario calcula a forca entre eles
        for(int j=0; j<cenario->getListadeObstaculosSize(); j++){
            distancia = sqrt( pow( (cenario->getNPC(i)->getxCont() - convertGridMundo(cenario->getObstaculo(j)->getx()) ), 2)+ pow( (cenario->getNPC(i)->getyCont() - convertGridMundo(cenario->getObstaculo(j)->gety()) ), 2) ) ;
            angulo = asin( (double)(cenario->getNPC(i)->getyCont() - convertGridMundo(cenario->getObstaculo(j)->gety())  )/distancia ) ;

            if( convertGridMundo(cenario->getObstaculo(j)->getx()) < cenario->getNPC(i)->getxCont() )forcaX += ( cenario->getObstaculo(j)->getForca()/pow(distancia,2) )*cos(angulo);
            else forcaX += (-1) *( cenario->getObstaculo(j)->getForca()/pow(distancia,2) )*cos(angulo);

            forcaY += ( cenario->getObstaculo(j)->getForca()/pow(distancia,2) )*sin(angulo);

        }
		
		//limita a velocidade do agente
        if( forcaX/10000 > 0.02 || forcaX/10000 < -0.02){
            if (forcaX > 0)cenario->getNPC(i)->setxCont( cenario->getNPC(i)->getxCont() + 0.02 );
            else cenario->getNPC(i)->setxCont( cenario->getNPC(i)->getxCont() - 0.02 );
        }
        else{
            cenario->getNPC(i)->setxCont( cenario->getNPC(i)->getxCont() + forcaX/10000 );
        }

        if( forcaY/10000 > 0.02 || forcaY/10000 < -0.02){
            if(forcaY>0)cenario->getNPC(i)->setyCont( cenario->getNPC(i)->getyCont() + 0.02 );
            else cenario->getNPC(i)->setyCont( cenario->getNPC(i)->getyCont() - 0.02 );
        }
        else{
            cenario->getNPC(i)->setyCont( cenario->getNPC(i)->getyCont() + forcaY/10000 );
        }

    }
